﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Spinning.Spinning.Entity.Scenes;
using Spinning.Spinning.Entity;
using Spinning.Spinning.Unitity;
using Microsoft.Xna.Framework;
using ShakeGestures;
using System.Net;

namespace Spinning.Spinning.Scenes.BattleScene
{
    class UserEarnBattleScene : BaseScene
    {
        AnimationSprite spriteSpinning, spriteArrow, timerSprite, timerSprite10, cycleSprite, cycleSprite10;
        Sprite spriteArrow2;
        CircleGesture cg; 
        float pos_X;
        TextEntity te;
        bool isTimesUp = false;
        bool isEarnDone = false, isEnemyEarnDone = false;

        int cycleCount, endTimer;

        private UdpAnySourceMulticastChannel Channel { get; set; }


        protected String stageName;

        public UserEarnBattleScene(String stage) 
        {
            stageName = stage;
        }

        public override void OnLoad()
        {
            base.OnLoad();
            endTimer = 10;//倒數10秒
            Sprite backGroundSprite = new Sprite();
            backGroundSprite.textureName = "bg";
            backGroundSprite.ZIndex = Constants.background;
            backGroundSprite.OnLoad();
            this.Attach(backGroundSprite);

            cg = new CircleGesture();
            cg.Position = new Vector2(240, 550);
            cg.BigRadius = 260;
            cg.SmailRadius = 0;
            cg.ZIndex = Constants.debugText;
            //cg.OnLoad();
            TouchManager.RegisteTouchArea(cg);
            this.Attach(cg);
            cg.OnRunCircleEvent += AddCycleCount;
            cg.OnAreaChangeEvent += OnAreaChange;

            spriteSpinning = new AnimationSprite();
            spriteSpinning.textureName = "pvp/big_spin";
            spriteSpinning.Position = new Vector2(240 - 157, 550 - 131);
            pos_X = spriteSpinning.Position.X;
            spriteSpinning.ZIndex = Constants.player;
            spriteSpinning.OnLoad();
            switch (Game1.stageManager.GameSrate.CurrentPlayer) 
            {
                case Constants.PlayerId.Phi:
                    spriteSpinning.SetAnimation(new Point(1, 3), new int[] { 0 });
                    break;
                case Constants.PlayerId.Theta:
                    spriteSpinning.SetAnimation(new Point(1, 3), new int[] { 1 });
                    break;
                case Constants.PlayerId.Omega:
                    spriteSpinning.SetAnimation(new Point(1, 3), new int[] { 2 });
                    break;
            }
            spriteSpinning.Alpha = 1;
            this.Attach(spriteSpinning);

            spriteArrow = new AnimationSprite();
            spriteArrow.textureName = "wind/arrow";
            spriteArrow.Position = new Vector2(240 - 206, 390);
            spriteArrow.ZIndex = Constants.player;
            spriteArrow.OnLoad();
            spriteArrow.SetAnimation(new Point(2, 2), new int[] { 0 });
            spriteArrow.Alpha = 1;
            this.Attach(spriteArrow);

            spriteArrow2 = new Sprite();
            spriteArrow2.textureName = "wind/arrow_orange";
            spriteArrow2.Position = new Vector2(240 - 170, 240);
            spriteArrow2.ZIndex = Constants.player;
            spriteArrow2.OnLoad();
            spriteArrow2.Alpha = 0;
            this.Attach(spriteArrow2);

            Sprite timerBG = new Sprite();
            timerBG.textureName = "singleGameBase/white_line_bgs";
            timerBG.ZIndex = Constants.background;
            timerBG.Position = new Vector2(50, 35); 
            timerBG.OnLoad();
            this.Attach(timerBG);

            Sprite cycleBg = new Sprite();
            cycleBg.textureName = "singleGameBase/black_transparent";
            cycleBg.ZIndex = Constants.background;
            cycleBg.Position = new Vector2(310, 50);
            cycleBg.OnLoad();
            this.Attach(cycleBg);

            timerSprite = new AnimationSprite();
            timerSprite.textureName = "number";
            timerSprite.ZIndex = Constants.player;
            timerSprite.OnLoad();
            timerSprite.SetAnimation(new Point(3, 4));
            timerSprite.Position = new Vector2(120, 45);
            this.Attach(timerSprite);

            timerSprite10 = new AnimationSprite();
            timerSprite10.textureName = "number";
            timerSprite10.ZIndex = Constants.player;
            timerSprite10.OnLoad();
            timerSprite10.SetAnimation(new Point(3, 4));
            timerSprite10.Position = new Vector2(60, 45);
            this.Attach(timerSprite10);

            Sprite timeSecond = new Sprite();
            timeSecond.textureName = "second";
            timeSecond.ZIndex = Constants.player;
            timeSecond.OnLoad();
            timeSecond.Position = new Vector2(185, 80);
            this.Attach(timeSecond);

            cycleSprite = new AnimationSprite();
            cycleSprite.textureName = "singlePlayerMenu/number";
            cycleSprite.ZIndex = Constants.player;
            cycleSprite.OnLoad();
            cycleSprite.SetAnimation(new Point(3, 4));
            cycleSprite.Position = new Vector2(380, 50);
            this.Attach(cycleSprite);

            cycleSprite10 = new AnimationSprite();
            cycleSprite10.textureName = "singlePlayerMenu/number";
            cycleSprite10.ZIndex = Constants.player;
            cycleSprite10.OnLoad();
            cycleSprite10.SetAnimation(new Point(3, 4));
            cycleSprite10.Position = new Vector2(320, 50);
            this.Attach(cycleSprite10);

            te = new TextEntity();
            ResourceManager.ContentRoot = "";
            te.fontString = "CenturyGothicBold";
            te.OnLoad();
            te.Origin = new Vector2(0.5f);
            te.Position = new Vector2(240, 400);
            te.Color = Color.Red;
            //te.Alpha = 1;
            te.ZIndex = Constants.debugText;
            Attach(te);
            te.Value = "";

            this.Channel = new UdpAnySourceMulticastChannel(IPAddress.Parse("224.0.1.100"), 3000);
            this.Channel.AfterOpen += new EventHandler(Channel_AfterOpen);
            this.Channel.BeforeClose += new EventHandler(Channel_BeforeClose);
            this.Channel.PacketReceived += new EventHandler<UdpPacketReceivedEventArgs>(Channel_PacketReceived);

            this.Channel.Open();

            ShakeGesturesHelper.Instance.ShakeGesture += Instance_ShakeGesture;
            ShakeGesturesHelper.Instance.MinimumRequiredMovesForShake = 2;
            ShakeGesturesHelper.Instance.Active = false;

            SortChildren();
        }

        public void Instance_ShakeGesture(object sender, ShakeGestureEventArgs e)
        {
            ShakeGesturesHelper.Instance.ShakeGesture -= Instance_ShakeGesture;
            ShakeGesturesHelper.Instance.Active = false;
            Game1.stageManager.LifeTimeEarnByUser = cycleCount;
            this.Channel.Send("hostId:{0},clientId:{1},isHost:{2},isEarnDone:{3},CurrentPlayer:{4},PlayerSpinningType:{5},PlayerEarnLife:{6},",
                Game1.hostId, Game1.clientId, Game1.stageManager.IsHost, true, Game1.stageManager.GameSrate.CurrentPlayer, Game1.stageManager.GameSrate.PlayerSpinningType, cycleCount);
            isEarnDone = true;
            te.Value = "Waiting For Your Enemy!!";
            spriteSpinning.Visable = false;
            spriteArrow2.Visable = false;
        }

        public void AddCycleCount() 
        {
            if (!isTimesUp)
                cycleCount++;
        }

        int _gameTime;
        protected override void UpdateSelf(GameTime gameTime)
        {
            base.UpdateSelf(gameTime);
            int delta = gameTime.ElapsedGameTime.Milliseconds;
            _gameTime += delta;
            if (!isTimesUp)
            {
                if (_gameTime / 1000 >= 1)
                {
                    _gameTime = _gameTime % 1000;
                    endTimer--;
                    if (endTimer == 0)
                        OnTimesUp();
                }
            }

            SetTimerSprite(endTimer);
            SetCycleSprite(cycleCount);
            if (!cg.isPress) spriteArrow.SetChangeFrameAnimation(new int[] { 0 });
            //te.Value = "C Count:" + cycleCount;

            if (isEnemyEarnDone && isEarnDone)
            {
                Game1.stageManager.GoToScene(stageName);
            }

        }

        void OnAreaChange()
        {
            spriteArrow.SetChangeFrameAnimation(new int[] { adjustInt(cg.CurrentArea) });
        }

        int adjustInt(int a)
        {
            switch (a)
            {
                case 0:
                    return 1;
                case 1:
                    return 3;
                case 2:
                    return 2;
            }
            return 0;
        }

        void SetTimerSprite(int i)
        {
            if (i < 0) i = 0;
            timerSprite10.SetChangeFrameAnimation(new int[] { i / 10 });
            timerSprite.SetChangeFrameAnimation(new int[] { i % 10 });
        }

        void SetCycleSprite(int i)
        {
            if (i < 0) i = 0;
            cycleSprite10.SetChangeFrameAnimation(new int[] { i / 10 });
            cycleSprite.SetChangeFrameAnimation(new int[] { i % 10 });
        }

        public void OnTimesUp() 
        {
            isTimesUp = true;
            spriteArrow.Alpha = 0;
            spriteArrow2.Alpha = 1;
            ShakeGesturesHelper.Instance.Active = true;
            //Game1.stageManager.LifeTimeEarnByUser = cycleCount;
            //Game1.stageManager.GoToScene(stageName);
        }

        void Channel_PacketReceived(object sender, UdpPacketReceivedEventArgs e)
        {
            //if(e.Message.Length!=0)
            //te.Value = e.Message;

            string[] temp;
            string[] temp1;

            temp = e.Message.Split(',');

            NoKeyFoundDictionary dataDictionary = new NoKeyFoundDictionary();

            for (int i = 0; i < temp.Length; i++)
            {
                temp1 = temp[i].Split(':');
                if (temp1.Length >= 2)
                    dataDictionary.Add(temp1[0], temp1[1]);
            }

            if (Game1.stageManager.IsHost)
            {
                if (dataDictionary.Get("hostId") == Game1.hostId && dataDictionary.Get("clientId") == Game1.clientId && dataDictionary.Get("isHost") == "False" && dataDictionary.Get("isEarnDone") == "True")
                {
                    MappingToBattleData(dataDictionary.Get("CurrentPlayer"), dataDictionary.Get("PlayerSpinningType"), dataDictionary.Get("PlayerEarnLife"));
                    isEnemyEarnDone = true;
                }
            }
            else 
            {
                if (dataDictionary.Get("hostId") == Game1.hostId && dataDictionary.Get("clientId") == Game1.clientId && dataDictionary.Get("isHost") == "True" && dataDictionary.Get("isEarnDone") == "True")
                {
                    MappingToBattleData(dataDictionary.Get("CurrentPlayer"), dataDictionary.Get("PlayerSpinningType"), dataDictionary.Get("PlayerEarnLife"));
                    isEnemyEarnDone = true;
                }
            }
        }

        void MappingToBattleData(string player,string spin, string life) 
        {
            switch (player) 
            {
                case "Omega":
                    Game1.stageManager.BattleData.CurrentEnemy = Constants.PlayerId.Omega;
                    break;
                case "Phi":
                    Game1.stageManager.BattleData.CurrentEnemy = Constants.PlayerId.Phi;
                    break;
                case "Theta":
                    Game1.stageManager.BattleData.CurrentEnemy = Constants.PlayerId.Theta;
                    break;
            }

            switch (spin) 
            {
                case "Omega":
                    Game1.stageManager.BattleData.EnemySpinningType = Constants.SpinningType.Omega;
                    break;
                case "Phi":
                    Game1.stageManager.BattleData.EnemySpinningType = Constants.SpinningType.Phi;
                    break;
                case "Theta":
                    Game1.stageManager.BattleData.EnemySpinningType = Constants.SpinningType.Theta;
                    break;

                case "India":
                    Game1.stageManager.BattleData.EnemySpinningType = Constants.SpinningType.India;
                    break;
                case "Russia":
                    Game1.stageManager.BattleData.EnemySpinningType = Constants.SpinningType.Russia;
                    break;
                case "Tiawan":
                    Game1.stageManager.BattleData.EnemySpinningType = Constants.SpinningType.Tiawan;
                    break;
            }

            Game1.stageManager.BattleData.EnemyLifeTimeEarn = Convert.ToInt32(life);
            
        }

        void Channel_BeforeClose(object sender, EventArgs e)
        {
            this.Channel.Send("END,{0}, leaves the UDP Multicast chat,", Game1.hostId);
        }

        void Channel_AfterOpen(object sender, EventArgs e)
        {
            this.Channel.Send("BEGIN,{0}, enters the UDP Multicast chat,", Game1.hostId);
        }

        public override BaseScene Clone()
        {
            BaseScene scene = new UserEarnBattleScene(stageName);
            scene.Size = new Vector2(Constants.Window_Width, Constants.Window_Height);
            scene.OnLoad();
            scene.SortChildren();
            return scene;
        }
    }
}
